#include "CenterJudgeManager.h"
#include "StringConverter.h"
#include "ResourceManager.h"
#include "Database/DatabaseEnv.h"
#include "StringConverter.h"
#include "json/json.h"
#include "NGLog.h"
#include "Character.h"
#include "CharManager.h"
#include "Items.h"
#include "ItemManager.h"
#include "Users.h"
#include "UserManager.h"
#include "Channels.h"
#include "ChannelManager.h"
#include "Towns.h"
#include "TownManager.h"
#include "ItemModelManager.h"
#include "Message.h"
#include "CenterBankManager.h"
#include "VipCardManager.h"
#include "Tools.h"
#include "XMLData.h"
#include "GameDefine.h"
#include XMLDATA_MGR_PATH
#include LOGIC_MGR_PATH
#include LOG_MGR_PATH
#include PROTOCOLS_MGR_PATH
#include "OpcodesEx.h"
#include "WorldPacket.h"
#include "AIInterface.h"
#include "WSSocketManager.h"
#include "json/json.h"
#include "ProtocolDealEnums.h"
#include "url.h"
#include "CRUsersManager.h"
#include "CRGeolocationManager.h"

//=============================组局信息相关===================================
bool CenterJudgeManager::AddCenterJudge(CenterJudge & cj)
{
	Fields fields;
	sDataMgr.initData(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, &fields);
	
	fields["status"] = cj.status;
	fields["type"] = cj.type;
	fields["pid"] = cj.pid;
	fields["nickname"] = cj.nickname;
	fields["icon_url"] = cj.icon_url;
	fields["target_id"] = cj.target_id;
	fields["target_type"] = cj.target_type;
	fields["judge_pid"] = cj.judge_pid;
	fields["judge_nickname"] = cj.judge_nickname;
	fields["judge_icon_url"] = cj.judge_icon_url;
	fields["judge_level"] = cj.judge_level;
	fields["label_id"] = cj.label_id;
	fields["label_info"] = cj.label_info;
	fields["judge_info"] = cj.judge_info;
	fields["create_time"] = cj.create_time;
	fields["coord_latitude"] = cj.coord_latitude;
	fields["coord_longitude"] = cj.coord_longitude;
	fields["coord_altitude"] = cj.coord_altitude;
	
	if (!sDataMgr.insertData(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, &fields))
		return false;
	
	cj.judge_id = fields["judge_id"].GetUInt32();
	return true;
}

bool CenterJudgeManager::UpdateCenterJudge(const CenterJudge & cj)
{
	Fields fields;
	
	fields["judge_id"] = cj.judge_id;
	fields["status"] = cj.status;
	fields["type"] = cj.type;
	fields["pid"] = cj.pid;
	fields["nickname"] = cj.nickname;
	fields["icon_url"] = cj.icon_url;
	fields["target_id"] = cj.target_id;
	fields["target_type"] = cj.target_type;
	fields["judge_pid"] = cj.judge_pid;
	fields["judge_nickname"] = cj.judge_nickname;
	fields["judge_icon_url"] = cj.judge_icon_url;
	fields["judge_level"] = cj.judge_level;
	fields["label_id"] = cj.label_id;
	fields["label_info"] = cj.label_info;
	fields["judge_info"] = cj.judge_info;
	fields["create_time"] = cj.create_time;
	fields["coord_latitude"] = cj.coord_latitude;
	fields["coord_longitude"] = cj.coord_longitude;
	fields["coord_altitude"] = cj.coord_altitude;
	
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, 
									&fields, "`judge_id` = %u", cj.judge_id);
	
	return count > 0;
}

#define SQLBUFER_LEN 16384

bool CenterJudgeManager::UpdateCenterJudge(Fields * fields, const char * QueryString, ...)
{
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, QueryString); 
	vsnprintf(sql, SQLBUFER_LEN, QueryString, vlist); 
	va_end(vlist);
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, fields, sql);
	return count > 0;
}

bool CenterJudgeManager::UpdateCenterJudge(const uint32 &cj_id, Fields * fields)
{
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, fields, 
												"`judge_id` = %u", cj_id);
	return count > 0;
}


bool CenterJudgeManager::GetCenterJudge(const uint32 & cj_id, CenterJudge * cj)
{
	assert (cj);
	FieldRows rows;
	sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, &rows, "`judge_id` = %u", cj_id);
	if (rows.empty())
		return false;
	
	Fields fields = rows.front();
	cj->judge_id = fields["judge_id"].GetUInt32();
	cj->status = fields["status"].GetUInt32();
	cj->type = fields["type"].GetUInt32();
	
	cj->pid = fields["pid"].GetUInt32();
	cj->nickname = fields["nickname"].GetValue();
	cj->icon_url = fields["icon_url"].GetValue();
	cj->target_id = fields["target_id"].GetUInt32();
	cj->target_type = fields["target_type"].GetUInt32();
	cj->judge_pid = fields["judge_pid"].GetUInt32();
	cj->judge_nickname = fields["judge_nickname"].GetValue();
	cj->judge_icon_url = fields["judge_icon_url"].GetValue();
	cj->judge_level = fields["judge_level"].GetUInt32();
	cj->label_id = fields["label_id"].GetUInt32();
	cj->label_info = fields["label_info"].GetValue();
	cj->judge_info = fields["judge_info"].GetValue();
	cj->create_time = fields["create_time"].GetUInt32();
	
	cj->coord_latitude = fields["coord_latitude"].GetDouble();
	cj->coord_longitude = fields["coord_longitude"].GetDouble();
	cj->coord_altitude = fields["coord_altitude"].GetDouble();
	
	return true;
}

uint32 CenterJudgeManager::GetCenterJudgeList(std::list<CenterJudge> * lstData, const char * query,...)
{
	va_list argp;
	va_start(argp, query);
	lstData->clear();
	FieldRows fieldRows;
	
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, query); 
	vsnprintf(sql, SQLBUFER_LEN, query, vlist); 
	va_end(vlist);
	
	if (!sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, &fieldRows, sql))
		return 0;
	
	FieldRows::iterator iter, enditer = fieldRows.end();
	for (iter = fieldRows.begin(); iter != enditer; ++ iter)
	{
		CenterJudge cj;
		Fields &fields = *iter;
		
		cj.judge_id = fields["judge_id"].GetUInt32();
		cj.status = fields["status"].GetUInt32();
		cj.type = fields["type"].GetUInt32();
		
		cj.pid = fields["pid"].GetUInt32();
		cj.nickname = fields["nickname"].GetValue();
		cj.icon_url = fields["icon_url"].GetValue();
		cj.target_id = fields["target_id"].GetUInt32();
		cj.target_type = fields["target_type"].GetUInt32();
		cj.judge_pid = fields["judge_pid"].GetUInt32();
		cj.judge_nickname = fields["judge_nickname"].GetValue();
		cj.judge_icon_url = fields["judge_icon_url"].GetValue();
		cj.judge_level = fields["judge_level"].GetUInt32();
		cj.label_id = fields["label_id"].GetUInt32();
		cj.label_info = fields["label_info"].GetValue();
		cj.judge_info = fields["judge_info"].GetValue();
		cj.create_time = fields["create_time"].GetUInt32();
		
		cj.coord_latitude = fields["coord_latitude"].GetDouble();
		cj.coord_longitude = fields["coord_longitude"].GetDouble();
		cj.coord_altitude = fields["coord_altitude"].GetDouble();
		
		lstData->push_back(cj);
	}
	
	return lstData->size();
}

// 获得评价列表
bool CenterJudgeManager::GetjudgeList(std::list<CenterJudge> * lstCJ, const uint32 & pid, const uint32 & offset, const uint8 & num)
{
	lstCJ->clear();
	
	FieldRows fieldRows;
	sDataMgr.queryDatas(DataManager::DatabaseTypeCenter, DB_NAME_CENTERJUDGE, &fieldRows, 
						"max(judge_id) as `judge_id`", "`pid` = %u and `status` < 255 order by `create_time` desc limit %u, %u", pid, offset, num);
	
	if(fieldRows.size())
	{
		std::vector<Fields>::iterator itField, eiField = fieldRows.end();
		for(itField = fieldRows.begin(); itField!=eiField; ++itField)
		{
			std::map<String,Field>::iterator itMap, eiMap = (*itField).end();
			for(itMap = (*itField).begin(); itMap!=eiMap; ++itMap)
			{
				uint32 judge_id = (itMap->second).GetUInt32();
				CenterJudge cj;
				if(GetCenterJudge(judge_id, &cj))
					lstCJ->push_back(cj);
			}
		}
	}
	
	
	return true;
}

// 玩家对玩家进行评价
uint8 CenterJudgeManager::PlayerJudge(CharPtr & pChr, const uint32 & target_id, const uint32 & target_type, const uint32 & pid, const uint32 & judge_pid, const uint8 & level, std::vector<uint8> vLabel, String judge_info)
{
	if(pChr.isNull())
		return 0;
	
	uint8 result = 1;
	CRUser cr_user;
	CRUser cr_judgeUser;
	do
	{
		if(pid == judge_pid)
		{// 不能对自己进行评价
			result = 2;
			break;
		}
		
		// 用户不存在
		if(!sCRUsersMgr.GetCRUser(pid, &cr_user))
		{
			result = 3;
			break;
		}
		
		// 被评价的目标玩家不存在
		if(!sCRUsersMgr.GetCRUser(judge_pid, &cr_judgeUser))
		{
			result = 3;
			break;
		}
		
		if(target_type == 1)
		{// 对组局玩家进行评价
			std::list<CenterBattle> lstData;
			if(!sCenterBattleMgr.GetCenterBattleList(&lstData, "cb_id = %u", target_id))
			{// 错误的组局
				result = 4;
				break;
			}
			
			std::list<CenterJudge> lstCJ;
			if(GetCenterJudgeList(&lstCJ, "target_id = %u and pid = %u and judge_pid = %u", 
									target_id, pid, judge_pid))
			{// 已经对玩家进行过评价
				result = 5;
				break;
			}
			
			// 玩家未在组局中进行游戏
			CenterBattle cb = lstData.front();
			Json::Reader reader;
			Json::Value valP;
			reader.parse(cb.player, valP);
			
			bool bFindChar = false;
			for(Json::Value::iterator iterVal=valP.begin(); iterVal!=valP.end(); ++iterVal)
			{
				if(judge_pid == StringConverter::parseUnsignedInt(iterVal.key().asString()))
				{
					bFindChar = true;
					break;
				}
			}
			
			if(bFindChar == false)
			{
				if(judge_pid == cb.pid)
					bFindChar = true;
			}
			
			if(!bFindChar)
			{// 玩家未在该组局中进行游戏
				result = 6;
				break;
			}
		}
		
		if(level > 5)
		{// 错误的星级
			result = 7;
			break;
		}
		
		std::vector<uint8>::iterator iter, ei = vLabel.end();
		for(iter = vLabel.begin(); iter!=ei; ++iter)
		{
			Log.Debug("CenterJudgeManager::PlayerJudge","label_id[%u]", *iter);
			if(!sXmlDataMgr.IsJudgeLabelIDExist(*iter))
			{// 无效的好友标签
				result = 8;
				break;
			}
		}
		
	}while(0);
	
	// 发送操作结果
	WorldPacket packet;
	if(sProtocolsMgr.CreateJudgePlayerResultPacket(&packet, target_id, target_type, pid, judge_pid, level, vLabel, judge_info, result))
		sGLMgr.SendProtocolsToChr(pChr,&packet);
	
	if(result == 1)
	{// 成功后处理对应逻辑
		// 评价总数和总分
		cr_judgeUser.judge_count++;
		cr_judgeUser.judge_total_stars += level;
		// 平均星级
		cr_judgeUser.judge_level = double(cr_judgeUser.judge_total_stars) / double(cr_judgeUser.judge_count);
		
		// 标签统计
		Json::Reader reader;
		Json::Value val;
		reader.parse(cr_judgeUser.judge_effect_label, val);
		
		if(val.size())
		{// 更新数据
			for (Json::Value::iterator iterV=val.begin(); iterV!=val.end(); ++iterV)
			{
				std::vector<uint8>::iterator iter, ei = vLabel.end();
				for(iter = vLabel.begin(); iter!=ei; ++iter)
				{
					if(StringConverter::parseUnsignedInt(iterV.key().asString()) == *iter)
					{
						uint32 new_count = (*iterV).asUInt() + 1;
						val[iterV.key().asString()] = new_count;
						break;
					}
				}
				
			}
		}
		else
		{// 初始数据
			std::map<uint32, String> mapJudgeID = sXmlDataMgr.GetJudgeLabelIDMap();
			std::map<uint32, String>::iterator iter, ei = mapJudgeID.end();
			for(iter = mapJudgeID.begin(); iter!=ei; ++iter)
			{
				uint32 count = 0;
				std::vector<uint8>::iterator iterV, eiV = vLabel.end();
				for(iterV = vLabel.begin(); iterV!=eiV; ++iterV)
				{
					if(iter->first == *iterV)
					{
						count = 1;
						break;
					}
				}
				
				val[StringConverter::toString(iter->first)] = count;
			}
		}
		
		Json::FastWriter w;
		cr_judgeUser.judge_effect_label = w.write(val); // 标签统计数据
		
		// 更新cr_users数据
		Fields fields;
		fields["judge_count"] = cr_judgeUser.judge_count;
		fields["judge_total_stars"] = cr_judgeUser.judge_total_stars;
		fields["judge_level"] = cr_judgeUser.judge_level;
		fields["judge_effect_label"] = cr_judgeUser.judge_effect_label;
		
		sCRUsersMgr.UpdateCRUser(cr_judgeUser.uid, &fields);
		
		Json::Value val2;
		for(uint8 i=0; i<vLabel.size(); ++i)
		{
			val2[i] = vLabel[i];
		}
		
		// 单条评价记录数据生成
		CenterJudge cj;
		cj.status = 1;					//状态
		cj.type = 1;					//评价类型
		cj.target_id = target_id;		//目标ID
		cj.target_type = target_type;	//目标类型
		cj.pid = pid;					//评价人PID
		cj.judge_pid = judge_pid;		//被评价人PID
		cj.judge_level = level;			//评价星级（1-5星）
		if(vLabel.size())
			cj.label_info = w.write(val2);	//标签列表内容
		
		cj.judge_info = judge_info;		//评价内容
		cj.create_time = time(0);		//创建时间
		
		std::list<CRGeoLocation> lstData;
		sCRGeoLocationMgr.GetCRGeoLocationList(&lstData, "uid = %u", pid);
		if(lstData.size())
		{
			CRGeoLocation crGeo = lstData.front();
			
			cj.coord_latitude = crGeo.coord_latitude;	//纬度
			cj.coord_longitude = crGeo.coord_longitude;	//精度
			cj.coord_altitude = crGeo.coord_altitude;	//海拔
		}
		
		AddCenterJudge(cj);
	}
	
	return 1;
}

// 获得玩家组局评价过的玩家列表
std::vector<uint32> CenterJudgeManager::GetJudgedCenterBattlePidList(CharPtr & pChr, const uint32 & pid, const uint32 & target_id, const uint32 & target_type)
{
	std::vector<uint32> vPid;
	if(pChr.isNull())
		return vPid;
	
	if(target_type == 1)
	{
		std::list<CenterJudge> lstCJ;
		if(GetCenterJudgeList(&lstCJ, "target_id = %u and pid = %u", target_id, pid))
		{
			std::list<CenterJudge>::iterator iter, ei = lstCJ.end();
			for(iter = lstCJ.begin(); iter!=ei; ++iter)
			{
				vPid.push_back((*iter).judge_pid);
			}
			
		}
	}
	
	WorldPacket packet;
	if(sProtocolsMgr.CreateJudgeResultListPacket(&packet, target_id, target_type, vPid))
		sGLMgr.SendProtocolsToChr(pChr, &packet);
	
	return vPid;
}

